(function() {
  define(['backbone', 'lib/ajax_setup'], function(Backbone, ajaxSetup) {
    return Backbone.sync = function(method, model, options) {
      var ajaxPromise, getValue, methodMap, params, promise, type, urlError,
        _this = this;
      methodMap = {
        'create': 'POST',
        'update': 'PUT',
        'delete': 'DELETE',
        'read': 'GET'
      };
      getValue = function(object, prop) {
        if (!(object && object[prop])) {
          return null;
        }
        if (_.isFunction(object[prop])) {
          return object[prop]();
        } else {
          return object[prop];
        }
      };
      urlError = function() {
        throw new Error('A "url" property or function must be specified');
      };
      type = methodMap[method];
      options || (options = {});
      params = {
        type: type,
        dataType: 'json',
        cache: false,
        complete: function() {
          return $('#application-loading').remove();
        }
      };
      if (!options.data && model && (method === 'create' || method === 'update')) {
        params.contentType = 'application/x-www-form-urlencoded';
        params.traditional = true;
        params.data = model.toJSON();
      }
      if (!options.url) {
        params.url = getValue(model, 'url') || urlError();
      }
      if (type === 'DELETE' || type === 'PUT') {
        params.data || (params.data = {});
        params.data._method = type;
        params.type = 'POST';
        params.beforeSend = function(xhr) {
          return xhr.setRequestHeader('X-HTTP-Method-Override', type);
        };
      }
      promise = $.Deferred();
      ajaxPromise = $.ajax(_.extend(params, options));
      ajaxPromise.error(function(error) {
        ajaxSetup.error.apply(this, arguments);
        return promise.reject.apply(this, arguments);
      });
      ajaxPromise.done(function(json, status, ajaxObj) {
        return promise.resolve.apply(_this, arguments);
      });
      return promise;
    };
  });

}).call(this);
